package com.zhangsun.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhangsun.service.RedisService;
import com.zhangsun.system.entity.RoleEntity;
import com.zhangsun.system.entity.RoleResourceEntity;
import com.zhangsun.system.mapper.RoleMapper;
import com.zhangsun.system.mapper.RoleResourceMapper;
import com.zhangsun.system.service.RoleResourceService;
import com.zhangsun.system.service.RoleService;
import com.zhangsun.system.vo.role.RoleEditVo;
import com.zhangsun.system.vo.role.RolePageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author zhangsun
 * @since 2019-07-23
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleEntity> implements RoleService {

    @Autowired
    private RoleResourceMapper roleResourceMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RoleResourceService roleResourceService;

    @Override
    public List<RoleEntity> findRolesByUser(String userId) {
        String rolesObject = (String) redisService.get(userId + ":role");
        if (StrUtil.isNotBlank(rolesObject)) {
            return JSON.parseArray(rolesObject, RoleEntity.class);
        }

        List<RoleEntity> roles = baseMapper.findRolesByUser(userId);
        redisService.set(userId + ":role", JSON.toJSONString(roles));
        return roles;
    }

    @Override
    public Object findAll(RolePageVo vo) {
        if (!vo.getPage()) {
            return baseMapper.findAll(vo);
        }

        Page<RoleEntity> page = new Page<>(vo.getCurrent(), vo.getSize());
        return baseMapper.findAll(page, vo);
    }

    @Transactional
    @Override
    public void create(RoleEditVo vo) {
        RoleEntity roleEntity = new RoleEntity();
        BeanUtil.copyProperties(vo, roleEntity);
        roleEntity.insert();

        roleResourceService.saveBatch(getRoleResources(roleEntity.getId(), vo.getResourceIds()));
    }

    @Override
    public RoleEntity findById(String id) {
        RoleEntity roleEntity = baseMapper.selectById(id);
        if (roleEntity != null) {
            LambdaQueryWrapper<RoleResourceEntity> queryWrapper = new QueryWrapper<RoleResourceEntity>().lambda();
            queryWrapper.eq(RoleResourceEntity::getRoleId, id);
            List<RoleResourceEntity> roleResources = roleResourceMapper.selectList(queryWrapper);
            roleEntity.setRoleResources(roleResources);
        }
        return roleEntity;
    }

    @Transactional
    @Override
    public void update(String id, RoleEditVo vo) {
        RoleEntity roleEntity = new RoleEntity();
        BeanUtil.copyProperties(vo, roleEntity);
        roleEntity.setId(id);
        roleEntity.updateById();

        LambdaQueryWrapper<RoleResourceEntity> queryWrapper = new QueryWrapper<RoleResourceEntity>().lambda();
        queryWrapper.eq(RoleResourceEntity::getRoleId, id);
        roleResourceMapper.delete(queryWrapper);
        roleResourceService.saveBatch(getRoleResources(roleEntity.getId(), vo.getResourceIds()));
    }

    private List<RoleResourceEntity> getRoleResources(String roleId, List<String> resourceIds) {
        List<RoleResourceEntity> roleResources = new ArrayList<>();
        for (String resourceId : resourceIds) {
            RoleResourceEntity roleResourceEntity = new RoleResourceEntity();
            roleResourceEntity.setRoleId(roleId);
            roleResourceEntity.setResourceId(resourceId);
            roleResources.add(roleResourceEntity);
        }
        return roleResources;
    }

    @Transactional
    @Override
    public void delete(String id) {
        baseMapper.deleteById(id);

        LambdaQueryWrapper<RoleResourceEntity> queryWrapper = new QueryWrapper<RoleResourceEntity>().lambda();
        queryWrapper.eq(RoleResourceEntity::getRoleId, id);
        roleResourceMapper.delete(queryWrapper);
    }
}
